package com.golxen.framework.common.server.agent;


import com.golxen.framework.CrossProtocol;
import com.golxen.framework.PBPacket.PBPacket;
import com.golxen.framework.common.queue.PlayerMQ;
import com.golxen.framework.common.server.game.cmd.Command;
import com.golxen.framework.common.server.game.cmd.CommandSet;
import com.golxen.framework.netty.session.agent.ServerClientMgr;
import com.golxen.protojava.SyncMessage;
import com.golxen.utils.LogUtil;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;

//代理调度，也充当命令线程包装类CommandWrapper
public class AbstractDispatcher implements Runnable {
    private static Logger logger = LogUtil.COMMON;

    private ChannelHandlerContext ctx;

    private PBPacket packet;

    private PlayerMQ player;

    long receiveTime;

    public AbstractDispatcher(ChannelHandlerContext ctx, PBPacket packet, PlayerMQ player) {
        this.ctx = ctx;
        this.packet = packet;
        this.receiveTime = System.currentTimeMillis();
        this.player = player;

    }

    /**
     * 线程池执行回调，执行线程并推动下一指令的执行
     */
    @Override
    public final void run() {
        try {
            int code = packet.getCode();
            if (code == CrossProtocol.C_CROSS_SERVICE_HANDLER) {
                SyncMessage.Request request = SyncMessage.Request.parseFrom(packet.getBytes());
                code = request.getCmdCode();
            }
            if (code > 0 && code < 10000) { // Client
                ServerClientMgr.routeClient(packet);
            } else if (code > 10000 && code < 20000) { // AgentServer
                handle(ctx, packet);
            } else if ((code > 20000 && code < 30000) // GameServer
                || (code > 120000 && code < 130000) // CrossServer response
            ) { // 
                ServerClientMgr.routeGame(packet);
            } else if ((code > 30000 && code < 50000) || (code > 130000 && code < 150000)) { // CrossServer
                // 普通跨服
                ServerClientMgr.routeCross(packet);
            } else {
                logger.warn("code {} not found router : ", code);
            }
        } catch (Exception e) {
            logger.error("execute command error, command: packet:" + packet.toString(), e);
        } finally {
            if (player != null) {
                /* 移除已经执行的指令 */
                player.getCommandQueue().remove();
            }
        }
    }

    void handle(ChannelHandlerContext ctx, PBPacket packet) {

        Command cmd;

        try {
            int code = packet.getCode();
            cmd = CommandSet.getCommand(code);
            if (cmd == null) {
                throw new RuntimeException(
                        "playerId=" + packet.getPlayerId() + " code=" + packet.getCode() + " is undefined");
            }
            cmd.execute(ctx, packet);
        } catch (Exception e) {
            new Command.Tuple(e, null);
        }

    }

    public static void dispatch(ChannelHandlerContext ctx, PBPacket pkt) {
        long playerId = pkt.getPlayerId();
        AgentPlayer player = AgentPlayerMgr.getOnlineUser(playerId);

        AbstractDispatcher dispatcher = new AbstractDispatcher(ctx, pkt, player);
        if (player != null) {
            player.getCommandQueue().add(dispatcher);
        } else {

            dispatcher.run();
        }

    }
}